#include <string>
#include <iostream>
#include "httplib.h"
#include "ContactsException.h"
#include "add_contact.pb.h"

using std::cin;
using std::cout;
using std::cerr;
using std::endl;
using namespace httplib;

const std::string ip = "127.0.0.1";
const uint32_t    port = 8080;

void meau()
{
    std::cout << "-----------------------------------------------------" <<std::endl;
    std::cout << "--------------- 请选择对通讯录的操作 ----------------" <<std::endl;
    std::cout << "------------------ 1、新增联系⼈ --------------------" <<std::endl;
    std::cout << "------------------ 2、删除联系⼈ --------------------" <<std::endl;
    std::cout << "------------------ 3、查看联系⼈列表 ----------------" <<std::endl;
    std::cout << "------------------ 4、查看联系⼈详细信息 ------------" <<std::endl;
    std::cout << "------------------ 0、退出 --------------------------" <<std::endl;
    std::cout << "-----------------------------------------------------" <<std::endl;
}

enum option
{
  QUIT = 0,
  ADD_IN,
  DEL,
  FIND_ALL,
  FIND_ONE
};

void buildAddContactRequest(add_contact::AddContactRequest *req)
{
  std::cout << "----------新增联系人----------" << std::endl;
  std::cout << "请输入联系人名称: ";
  std::string name;
  std::getline(std::cin, name);
  //设置联系人名称
  req->set_name(name);

  std::cout << "请输入联系人年龄: " ;
  int age;
  std::cin >> age;
  //设置联系人年龄
  req->set_age(age);

  std::cin.ignore(256,'\n');

  //添加电话
  for (int i = 0; ; ++i)
  {
    std::cout << "请输入电话号码" << i + 1 << ": ";
    std::string number;
    std::getline(std::cin, number);
    if (number.empty())
        break;
    
    //开空间
    add_contact::AddContactRequest_Phone * phone = req->add_phone();
    phone->set_number(number);

    std::cout << "请输入电话类型:(1. 移动电话  2. 固定电话):";
    int type;
    std::cin >> type;
    //忽略换行符
    std::cin.ignore(256, '\n');
    switch (type)
    {
      case 1: 
          phone->set_type(add_contact::AddContactRequest_Phone_PhoneType::AddContactRequest_Phone_PhoneType_MP);
          break;
      case 2:
          phone->set_type(add_contact::AddContactRequest_Phone_PhoneType::AddContactRequest_Phone_PhoneType_TEL);
          break;
      default:
          std::cout << "输入错误" << std::endl;
          break;
    }

  }
}
void ContactAdd()
{
  Client cli(ip, port);
  
  //构造 req
  add_contact::AddContactRequest req;
  buildAddContactRequest(&req);

  //序列化req 
  std::string req_str;
  if (!req.SerializeToString(&req_str))
  {
    throw ContactsException("AddcontactRequest序列化失败");
  }

  //发起post调用
  auto res =cli.Post("/contacts/add", req_str, "application/protobuf");
  if (!res)
  {
    std::string err_desc;
    err_desc.append("/contacts/add 链接失败！错误信息")
            .append(httplib::to_string(res.error()));
    throw ContactsException(err_desc);
  }

  //反序列化
  add_contact::AddContactResponse resp;
  bool parse = resp.ParseFromString(res->body);
  if (res->status != 200 && !parse)
  {
    std::string err_desc;
    err_desc.append("/contacts/add 调用失败")
            .append(std::to_string(res->status))
            .append("(").append(res->reason).append(")");
    throw ContactsException(err_desc);     
  }

  else if (res->status != 200)
  {
    std::string err_desc;
    err_desc.append("/contacts/add 调用失败")
            .append(std::to_string(res->status))
            .append("(")
            .append(res->reason).append(")错误原因:")
            .append(resp.error_desc());
    throw ContactsException(err_desc);

  }
  else if (!resp.sucess())
  {
    std::string err_desc;
    err_desc.append("/contacts/add 结果异常")
            .append("异常原因:")
            .append(resp.error_desc());
    throw ContactsException(err_desc);
  }

  //结果打印
  cout << "新增联系人成功, 联系人ID:" << resp.uid() << endl;
}

int main()
{
  while (true)
  {
    meau();
    cout << "--->请选择" << endl;
    int choose;
    cin >> choose;
    cin.ignore(256,'\n');
    try{
    switch(choose)
    {
      case option::QUIT:
          std::cout << "--->程序退出" << endl;
          return 0;
      case option::ADD_IN:
          ContactAdd();
          break;
      case option::DEL:
          break;
      case option::FIND_ALL:
          break;
      case option::FIND_ONE:
          break;
      default:
        cout << "输入错误重新输入" << endl;
    }
       }
    catch(ContactsException& e)
    {
      cout << "--->操作通讯库发生异常" << endl
      << "---> 异常信息:" << e.what() << endl;
    }
  }
  return 0;
}



















// int main()
// {
//     Client cli(ip, port);
//     Result res1 = cli.Post("/test-post");
//     if (res1->status == 200)
//     {
//       cout << "调用post成功" << endl;
//     }

//     Result res2  = cli.Get("/test-get");
//     if (res2->status== 200)
//     {
//       cout << "调用get 成功" << endl;
//     }
//     return 0;
// }
